package com.kusej.dbdocexport;

import com.intellij.database.psi.DbDataSource;
import com.intellij.database.psi.DbNamespace;
import com.intellij.database.psi.DbTable;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.psi.PsiElement;
import com.kusej.dbdocexport.model.DatabaseInfo;
import com.kusej.dbdocexport.model.TableColumnInfo;
import com.kusej.dbdocexport.model.TableIndexInfo;
import com.kusej.dbdocexport.model.TableInfo;
import com.kusej.dbdocexport.utils.DBExecutorUtils;
import com.kusej.dbdocexport.utils.ExcelExportUtils;
import com.kusej.dbdocexport.utils.ExcelUtils;
import com.kusej.dbdocexport.utils.FileUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.jetbrains.annotations.NotNull;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

public class DbDocExportExcel extends AnAction {
    @Override
    public void update(@NotNull AnActionEvent e) {
        // 根据特定条件判断是否禁用 Action
        PsiElement[] psiElements = e.getData(LangDataKeys.PSI_ELEMENT_ARRAY);
        if (psiElements == null) {
            e.getPresentation().setEnabled(false);
            return;
        }
        for (PsiElement psiElement : psiElements) {
            if (psiElement instanceof DbTable) {
                e.getPresentation().setEnabled(false);
                return;
            }
        }
        // 设置 Action 的状态
        e.getPresentation().setEnabled(true);
    }
    @Override
    public void actionPerformed(AnActionEvent e) {
        try {
            PsiElement[] psiElements = Objects.requireNonNull(e.getData(LangDataKeys.PSI_ELEMENT_ARRAY), "您未选择任何connection或db实例");
            Set<DbDataSource> dbList = new HashSet<>();
            List<DbNamespace> dbInstanceList = new ArrayList<>();
            for (PsiElement psiElement : psiElements) {
                if (psiElement instanceof DbDataSource) {
                    dbList.add((DbDataSource) psiElement);
                } else if (psiElement instanceof DbNamespace) {
                    dbInstanceList.add((DbNamespace) psiElement);
                }
            }
            if (dbList.isEmpty() && dbInstanceList.isEmpty()) {
                Messages.showErrorDialog("Message：您未选择任何connection或db实例", "ERROR");
                return;
            }
            List<String> schemaNames = Lists.newArrayList();
            if (!dbInstanceList.isEmpty()) {
                for (DbNamespace dbNamespace : dbInstanceList) {
                    schemaNames.add(dbNamespace.getName());
                    dbList.add(dbNamespace.getDataSource());
                }
            }
            if (dbList.size() > 1) {
                Messages.showErrorDialog("Message：暂不支持多个connection同时导出！", "ERROR");
                return;
            }
            DbDataSource dbDataSource = dbList.stream().findAny().get();// 数据库链接信息
            if (!Objects.requireNonNull(dbDataSource.getConnectionConfig()).getDriverClass().contains("mysql")){
                Messages.showErrorDialog("Message：目前仅支持MySQL数据库导出！", "ERROR");
                return;
            }
            exportExcel(dbDataSource, schemaNames);
            if (CollectionUtils.isNotEmpty(schemaNames)) {
                // 指定数据库实例导出
                Messages.showMessageDialog(String.format("Success：已导出%s实例到当前项目根目录", Arrays.toString(schemaNames.toArray())), "Message", AllIcons.Actions.Commit);
            } else {
                // 导出全部数据库实例
                Messages.showMessageDialog(String.format("Success：已导出【%s】下全部实例到当前项目根目录", dbDataSource.getName()), "Message", AllIcons.Actions.Commit);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            Messages.showErrorDialog(ex.getMessage(), "ERROR");
        }finally {
            LocalFileSystem.getInstance().refresh(true);
        }

    }

    private void exportExcel(DbDataSource dbDataSource, List<String> schemaNames) {
        try {
            if (CollectionUtils.isEmpty(schemaNames)) {
                schemaNames = DBExecutorUtils.getSchemas(dbDataSource);
            }
            for (String dbSchema : schemaNames
            ) {
                List<TableInfo> tableInfo = DBExecutorUtils.combineAllInfo(dbSchema,dbDataSource);
                DatabaseInfo databaseInfo = new DatabaseInfo();
                databaseInfo.setSchema(dbSchema);
                Workbook workbook = ExcelUtils.getWorkbookFromStream(
                        DBExecutorUtils.class.getClassLoader().getResourceAsStream("template.xlsx")
                );
                Sheet tableSheet = workbook.getSheet("数据库表目录");
                ExcelExportUtils.listToSheet(tableSheet,tableInfo, TableInfo.class);

                //模板方式控制样式
                Sheet tableDetailSheet = workbook.getSheet("数据库表结构");
                Row columnTableTitleRow = tableDetailSheet.getRow(0);
                Row columnTableCommentRow = tableDetailSheet.getRow(1);
                Row columnTableDataRow = tableDetailSheet.getRow(2);
                Row indexTableTitleRow = tableDetailSheet.getRow(3);
                Row indexTableCommentRow = tableDetailSheet.getRow(4);
                Row indexTableDataRow = tableDetailSheet.getRow(5);
                Row brRow = tableDetailSheet.getRow(6);

                int rowI = 7;
                for (TableInfo info : tableInfo) {
                    ExcelUtils.cloneRow(tableDetailSheet,columnTableTitleRow,rowI);
                    ExcelUtils.setValue(tableDetailSheet,rowI,0,(info.getTableName() + " " + info.getTableComment()).trim(),null);
                    rowI++;
                    ExcelUtils.cloneRow(tableDetailSheet,columnTableCommentRow,rowI);
                    rowI++;
                    for (TableColumnInfo tableColumnInfo : info.getColumnInfoList()) {
                        ExcelUtils.cloneRow(tableDetailSheet,columnTableDataRow,rowI);
                        ExcelUtils.setValue(tableDetailSheet,rowI,0,tableColumnInfo.getIndex(),null);
                        ExcelUtils.setValue(tableDetailSheet,rowI,1,tableColumnInfo.getColumnName(),null);
                        ExcelUtils.setValue(tableDetailSheet,rowI,2,tableColumnInfo.getColumnType(),null);
                        ExcelUtils.setValue(tableDetailSheet,rowI,3,tableColumnInfo.getColumnDefaultValue(),null);
                        ExcelUtils.setValue(tableDetailSheet,rowI,4,tableColumnInfo.getIsNullableStr(),null);
                        ExcelUtils.setValue(tableDetailSheet,rowI,5,tableColumnInfo.getColumnComment(),null);
                        rowI++;
                    }
                    ExcelUtils.cloneRow(tableDetailSheet,indexTableTitleRow,rowI);
                    rowI++;
                    ExcelUtils.cloneRow(tableDetailSheet,indexTableCommentRow,rowI);
                    rowI++;
                    for (TableIndexInfo tableIndexInfo : info.getIndexInfoList()) {
                        ExcelUtils.cloneRow(tableDetailSheet,indexTableDataRow,rowI);
                        ExcelUtils.setValue(tableDetailSheet,rowI,0,tableIndexInfo.getIndex(),null);
                        ExcelUtils.setValue(tableDetailSheet,rowI,1,tableIndexInfo.getIndexName(),null);
                        ExcelUtils.setValue(tableDetailSheet,rowI,2,tableIndexInfo.getIsUniqueStr(),null);
                        ExcelUtils.setValue(tableDetailSheet,rowI,3,tableIndexInfo.getRelatedColumn(),null);
                        ExcelUtils.setValue(tableDetailSheet,rowI,5,tableIndexInfo.getIndexComment(),null);
                        rowI++;
                    }
                    ExcelUtils.cloneRow(tableDetailSheet,brRow,rowI);
                    rowI++;
                }
                Path path = Paths.get(Objects.requireNonNull(dbDataSource.getProject().getBasePath()), dbSchema + "_数据库表.xlsx");
                ExcelUtils.saveWorkbook(path,workbook);
                System.out.println("完成了 " + dbSchema + " 导出到 " + path.toAbsolutePath());
            }


        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }

}
